/**
 *    @file       hashtable.h
 *
 *    @brief      
 *    @details
 *
 *    @version    1.0
 *    @date       12/19/2012 04:19:53 PM
 *
 *    @author     Theophilus (), wangtf418@gmail.com
 */
#ifndef _BF_HASHTABLE_H_
#define _BF_HASHTABLE_H_
#include "threadmutex.h"

#define HASHTABLE_LOCK(index) if (m_logflag) {m_lock[index].lock();}
#define HASHTABLE_UNLOCK(index) if (m_logflag) {m_lock[index].unlock();}

template<typename _Telem, template<typename> class _Tcontainer>
class hashtable
{
public:
	hashtable()
		: m_bucketlen(0), m_table(NULL), m_logflag(0), m_elemnum(0), m_lock(NULL)
	{
		
	}

	virtual ~hashtable()
	{
		if (m_table)
		{
			delete [] m_table;
		}
		
		if (m_lock)
		{
			delete [] m_lock;
		}
	}

public:
	virtual bf_int_t init(bf_int_t bucketlen, bf_int_t logflag = 0)
	{
		if (bucketlen <= 1)
		{
			return BF_ERROR;
		}
		m_bucketlen = bucketlen;
		m_logflag = logflag;
		m_table = new hash_container[m_bucketlen];
		if (m_logflag)
		{
			m_lock = new threadmutex[m_bucketlen];
		}
		return BF_OK;
	}

	virtual bf_int_t add(_Telem &elem, bf_int_t update = 0)
	{
		bf_int_t ret = BF_FALSE;
		bf_int_t index = elem.getindex() % m_bucketlen;
		HASHTABLE_LOCK(index)
		hash_iterator itr = m_table[index].begin();
		for (; itr != m_table[index].end(); itr ++)
		{
			if (elem == *itr)
			{
				break;
			}
		}

		if (itr == m_table[index].end())
		{
			m_table[index].push_back(elem);
			m_elemnum ++;
			ret = BF_TRUE;
		}
		else if (update)
		{
			*itr = elem;
		}
		HASHTABLE_UNLOCK(index)
		return ret;
	}

	virtual bf_int_t del(_Telem &elem)
	{
		bf_int_t ret = BF_FALSE;
		bf_int_t index = elem.getindex() % m_bucketlen;
		HASHTABLE_LOCK(index)
		hash_iterator itr = m_table[index].begin();
		for (; itr != m_table[index].end(); itr ++)
		{
			if (elem == *itr)
			{
				m_table[index].erase(itr);
				m_elemnum --;
				ret = BF_TRUE;
				break;
			}
		}
		HASHTABLE_UNLOCK(index)
		return ret;
	}
	
	virtual bf_int_t find(_Telem &elem)
	{
		bf_int_t ret = BF_FALSE;
		bf_int_t index = elem.getindex() % m_bucketlen;
		HASHTABLE_LOCK(index)
		hash_iterator itr = m_table[index].begin();
		for (; itr != m_table[index].end(); itr ++)
		{
			if (elem == *itr)
			{
				elem = *itr;
				ret = BF_TRUE;
				break;
			}
		}
		HASHTABLE_UNLOCK(index)
		return ret;
	}
protected:
	typedef _Tcontainer<_Telem> hash_container;
	typedef typename _Tcontainer<_Telem>::iterator hash_iterator;
	bf_int_t m_bucketlen;
	hash_container *m_table;
	bf_int_t m_logflag;
	bf_int_t m_elemnum;
	threadmutex *m_lock;
};

#endif

